package com.lovesher.payment.service.plugin.wechat;

import java.io.IOException;
import java.io.InputStream;
import java.net.SocketTimeoutException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.Map;

import javax.net.ssl.SSLContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.ConnectionPoolTimeoutException;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

/**
 * @Title: WeixinPayUtils.java
 * 
 * @Package com.rm.pay.payment.plugin.weixin
 * 
 * @Description: 微信支付工具类
 * 
 * @version V1.0
 */
public class WeixinPayUtils {

	private static Log log = LogFactory.getLog(WeixinPayUtils.class);

	/** 表示请求器是否已经做了初始化工作*/
	private static boolean hasInit = false;

	/** 连接超时时间，默认10秒*/
	private static int socketTimeout = 10000;

	/** 传输超时时间，默认30秒*/
	private static int connectTimeout = 30000;

	/** 请求器的配置*/
	private static RequestConfig requestConfig;

	/** HTTP请求器*/
	private static CloseableHttpClient httpClient;

	public static void init() {
		log.info("初始化微信支付证书开始...");
		KeyStore keyStore = null;
		try {
			keyStore = KeyStore.getInstance("PKCS12");
		} catch (KeyStoreException e1) {
			e1.printStackTrace();
		}
		InputStream instream = WeixinPayUtils.class.getResourceAsStream("/com/payment/weixin/apiclient_cert.p12");
		try {
			if (null == keyStore) {
				log.warn("初始化微信支付证书 keyStore 加载异常..");
				return;
			}
			keyStore.load(instream, "1521680121".toCharArray());
			log.info("初始化微信支付证书加载成功...");
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (CertificateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				instream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		SSLContext sslcontext = null;
		try {
			sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, "1521680121".toCharArray()).build();
		} catch (KeyManagementException e) {
			e.printStackTrace();
		} catch (UnrecoverableKeyException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (KeyStoreException e) {
			e.printStackTrace();
		}
		SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
		httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
		requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
		hasInit = true;
	}

	public static String sendPost(String url, Map<String, String> params) {
		if (!hasInit) {
			init();
		}
		String result = null;
		HttpPost httpPost = new HttpPost(url);
		String postDataXML = XmlUtils.toXml(params);
		log.info("微信支付发送报文内容:" + postDataXML);
		// 得指明使用UTF-8编码，否则到API服务器XML的中文不能被成功识别
		StringEntity postEntity = new StringEntity(postDataXML, "UTF-8");
		httpPost.addHeader("Content-Type", "text/xml");
		httpPost.setEntity(postEntity);
		// 设置请求器的配置
		httpPost.setConfig(requestConfig);
		try {
			HttpResponse response = httpClient.execute(httpPost);
			HttpEntity entity = response.getEntity();
			result = EntityUtils.toString(entity, "UTF-8");
			log.info("微信支付报文发送成功，返回结果:" + result);
		} catch (ConnectionPoolTimeoutException e) {
			log.error("http get throw ConnectionPoolTimeoutException(wait time out)",e);
		} catch (ConnectTimeoutException e) {
			log.error("http get throw ConnectTimeoutException",e);
		} catch (SocketTimeoutException e) {
			log.error("http get throw SocketTimeoutException",e);
		} catch (Exception e) {
			log.error("http get throw Exception",e);
		} finally {
			httpPost.abort();
		}
		return result;
	}
}
